<template>
  <el-row class="login-container" justify="center" :align="'middle'">
    <el-card style="max-width: 480px;">
      <h2 v-if="formType">注册</h2>
      <h2 v-if="!formType">登录</h2>
      <template #header>
        <div class="card-header">
          <img :src="imgURL" alt="">
        </div>
      </template>
      <div class="jump-link">
        <el-link target="_blank" type="primary" @click="handleChange">{{ formType === 0 ? '没有账号？去注册' :
          '已有账号？去登录' }}</el-link>
      </div>
      <!--      绑定输入内容                                                    绑定规则        绑定了对象提交时的表单验证 -->
      <el-form :model="loginForm" label-width="auto" style="max-width: 600px" :rules="rules" ref="loginFormRef">

        <el-form-item prop="userName"><!--这里的label就是在表单前面的显示-->
          <!-- 在这里placeholder就是对应的表单中未输入的信息，:prefix-icon就是显示在输入框上面的图标，这里能用不能使用 -->
          <el-input v-model="loginForm.userName" placeholder="用户名" :prefix-icon="User"></el-input>
          <!-- 上面的input标签里面都有:prefix-icon="Lock" 目前报错无法解析出来(因为没有引入这个包)，后续准备这一块放弃使用elementPlus -->
        </el-form-item>

        <el-form-item prop="passWord"><!--这里的label就是在表单前面的显示-->
          <el-input v-model="loginForm.passWord" placeholder="密码" type="password" :prefix-icon="Lock"></el-input>
        </el-form-item>

        <!-- 这里有prop才可以进行绑定 -->
        <el-form-item prop="validCode" v-if="formType">
          <el-input v-model="loginForm.validCode" style="max-width: 600px" placeholder="验证码" :prefix-icon="Lock">
            <template #append>
              <button @click="countDownChange">{{ countDown.validText }}</button>
            </template>
          </el-input>
        </el-form-item>

        <!-- 最后是表单的提交按钮 -->
        <el-form-item>
          <!--                        点击触发表单校验，方法是elementPlus的内置方法 -->
          <el-button type="primary" @click="submitForm(loginFormRef)" style="width: 100%;">{{ formType === 0 ? '登录' : '注册账号'
            }}</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </el-row>
</template>
<script setup>
import { ref, reactive } from 'vue';
import { getCode, userRegister,userLogin } from '../../api/index.js'
import {User, Lock} from '@element-plus/icons-vue' //这里引入特定的图标
import { useRouter } from 'vue-router';
const router = useRouter();
//下面这一行是引入静态资源的全新方式，值得参考
const imgURL = new URL('../../../public/妙妙！.jpg', import.meta.url).href

//通过一个变量来判断当前的状态是登录还是注册
const formType = ref(0); //这里为了方便显示登录和注册的信息，formType的值是0就是登录，1就是注册，因为我们通过v-if进行，0是false，1是true
const handleChange = () => {
  formType.value = !formType.value
}

//发送短信并开始倒计时
const countDown = reactive({
  validText: "获取验证码",
  time: 60
})
let flag = false;//这里是为了放置用户反复点击而导致的错乱，如果没有flag的话，用户的每一次点击都会要你创建一个定时器
const countDownChange = () => {
  if (flag) { return }//表示当前已经有了定时器，不能再继续添加
  //倒计时
  const time = setInterval(() => {
    //setIn terval是什么？就是每隔一段时间执行一次，这里就是每隔一秒执行一次
    if (countDown.time <= 0) {
      countDown.validText = "获取验证码";
      countDown.time = 60;
      flag = false;
      clearInterval(time)//清除计时器，防止内存泄漏
      return;
    } else {
      countDown.time--;
      countDown.validText = countDown.time + 's后重新获取'
    }
  }, 1000)
  flag = true;
  //下面是发送验证码的状态显示
  //下面是新知识点
  //Promise 是 JavaScript 中用于处理异步操作的对象。它代表了一个尚未完成但预期将来会完成的操作。Promise 对象有三种状态：
  // Pending（进行中）：初始状态，既不是成功，也不是失败状态。
  // Fulfilled（已成功）：意味着操作成功完成。
  // Rejected（已失败）：意味着操作失败。
  // Promise 对象有一个 then 方法，用于指定当 Promise 对象状态改变时的回调函数。
  // then 方法接受两个参数：一个是当 Promise 对象状态变为 fulfilled 时调用的函数，另一个是当 Promise 对象状态变为 rejected 时调用的函数。

  // 在你的代码中，getCode({tel: loginForm.userName}) 返回一个 Promise 对象，这个 Promise 对象会在 getCode 函数中的异步操作完成后被解决（resolved）或被拒绝（rejected）。
  //在我的getCode方法当中，处理过后的返回值会进入到data当中，data就是返回值，执行回调函数
  // .then 方法用于指定当 Promise 对象被解决时的回调函数。
  getCode({ tel: loginForm.userName }).then(({ data }) => {
    console.log(data, 'data')
    if (data.code === 10000) {
      ElMessage.success('发送成功')
    } else {
      ElMessage.error('发送失败')
    }
  })
}

//账号校验规则：
//新函数callback是回调函数
//正则表达式的使用
//新方法 .test() 方法用于检测一个字符串是否匹配某个模式。如果字符串中有匹配的值返回 true ，否则返回 false。
const validateUser = (rule, value, callback) => {//这个函数是校验用户名的函数，rule是规则，value是值，callback是回调函数
  if (value === '') {
    callback(new Error('请输入用户名')) //JS中抛出错误使用 throw new Error('错误信息')
  } else {
    // 手机号正则
    const phoneReg = /^1(3[0-9]|4[01456879]|5[0-35-9]|6[2567]|7[0-8]|8[0-9]|9[0-35-9])\d{8}$/
    if (phoneReg.test(value)) { //如果手机号符合正则表达式，那么就说明是正确的
      callback()
    } else {
      callback(new Error('请输入正确的手机号'))
    }
  }
}


const validatePassword = (rule, value, callback) => {
  if (value === '') {
    callback(new Error('请输入密码'))
  } else {
    // 密码正则
    const passwordReg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/ //这个正则表达式表示密码必须包含数字和字母，且长度在6-20之间
    if (passwordReg.test(value)) {
      callback()
    } else {
      callback(new Error('密码必须包含数字和字母，且长度在6-20之间'))
    }
  }
}
//密码的校验

//表单校验
//新属性 validator 自定义校验方法 ,trigger 触发时机
//trigger有三种主要的触发类型：
//blur：失去焦点时触发
//change：数据改变时触发
//focus：获得焦点时触发
const rules = reactive({ //这里直接绑定到对应的父标签就可以了，因为有trigger，当我的鼠标移开表单他就会启动验证方法
  userName: [{
    validator: validateUser, trigger: 'blur'
  }],//让他再失去焦点的时候触发这个函数
  passWord: [{
    validator: validatePassword, trigger: 'blur'
  }]
})


//表单的提交
const submitForm = async(formName) => {//formName是表单的名称
  if(!formName){//判断form实例有没有拿到
    return
  }
  await formName.validate((valid,fields) => {
    if (valid) {
      //这里面的loginForm是一个reactive对象，就在下面定义的
     console.log(loginForm,'submit!')
     console.log(formName,"formName")
     //这里还要进行判断用户是登录还hi验证
     //如果是注册页面
     if(formType.value){
       userRegister(loginForm).then(({data})=>{
         if(data.code === 10000){
           ElMessage.success('注册成功,请返回登录界面')
           formType.value=0;//跳转到登录页面
         }else{
           ElMessage.error('注册失败')
         }
       })
     }else{
       //如果是登录页面
       console.log('登录')
       userLogin(loginForm).then(({data})=>{
         if(data.code === 10000){
           ElMessage.success('登录成功')
           //我们还需要将用户信息和token保存到本地
           console.log(data,"data")
           localStorage.setItem('pz_token',data.data.token)
           localStorage.setItem('pz_userInfo',JSON.stringify(data.data.userInfo))
           //跳转到首页
           router.push('/')//之前一直显示找不到路由是因为没有创建路由实例，
         }else{
           ElMessage.error('登录失败')
         }
       })
     }
    } else {
      console.log('error submit!!',fields)
      return false
    }
  })
}

//通过ref获取表单的实例
const loginFormRef = ref()

//表单数据
const loginForm = reactive({
  userName: '',
  password: '',
  validCode: ''
})




</script>

<style scoped lang="less">
:deep(.el-card__header) {
  padding: 0
}

.login-container {
  height: 100%;

  .card-header {
    background-color: #899fe1;

    img {
      width: 430px;
    }
  }

  .jump-link {
    text-align: right;
    margin-bottom: 10px;
  }

  .el-input-group__append {
    button {
      width: 100%;
      height: 100%;
      background-color: transparent;
      border: none;
      color: gray;
    }
  }
}
</style>